/**
 * @file cutility.c
 * @brief Comandi d'utilità dell'applicativo.
 *
 * @date Feb 27, 2012
 * @author: Francesco Corvino
 */
#include "cutility.h"
#include <unistd.h>
#include "../invoker.h"
#include "../envFactory.h"
#include "../../RscApp/rscApplication.h"
#include "../../logproxy/logproxy.h"

/**
 * @brief Implemeta il comando help.
 *
 * Permette di stampare tutti i comandi registrati nell'applicazione.
 */
void exGetsAllCommands(){
	int i;
	DynArray* commands = RscApp_getCommands();
	AppLib_writeToHostF("Comandi registrati[%d]:\n",commands->numelement);

	log_namedlevel(CUTILITY_LOGNAME,LOG_DEBUG_LEVEL,
			"Avvio comando help, scrittura di %d comandi",commands->numelement);

	for(i=0;i< commands->numelement;i++){
		InterfaceCommand *cmd = (InterfaceCommand*) DynArray_getIndex(commands,i);
		char* outInfo = (char*) HiddenType_executeInterpreter(&(cmd->descriptorInfo),NULL);
		AppLib_writeToHostF( "%d * %s : %s \n", i,cmd->name,
				(outInfo==NULL)?("<<No info>>"):(outInfo));
	}
}

/**
 * @brief Effettua la chiusura del programma.
 */
void exCloseProgram(){
	AppLib_writeToHost("Avvio procedura di terminazione");
	AppLib_terminate();
}

/**
 * @brief Comando che restituisce le informazioni sulle sessioni.
 *
 * Restitusce le informazioni sulle sessioni attive e sulle elaborazioni
 * presenti per ogni sessione. La sessione in cui viene lanciato il comando dovrà contenere
 * almeno l'elaborazione relativa allo stesso comando.
 */
void exGetSessions(){
	int i;
	CMap* arr = RscApp_getAllSession();
	AppLib_writeToHostF("Sessioni presenti: %d\n",arr->values.numelement);
	for(i=0; i < arr->values.numelement;i++){
		HostSession *session = (HostSession*) CMap_getByIndex(arr,i);
		int numElab = session->threadsForSession.numelement;
		AppLib_writeToHostF("- Sessione %d -> %d threads attive",
				session->keySession, numElab);
		if(numElab!=0) {
			int iE = 0; DynArray* elabs = &(session->threadsForSession);
			AppLib_writeToHost(", tid associati:");
			for(iE = 0;iE<numElab;iE++){
				int key = ((ElaborationEntity*) DynArray_getIndex(elabs,iE))->keyElaboration;
				AppLib_writeToHostF(" (%d - %d);",iE,key);
			}
		}
		AppLib_writeToHost("\n");
	}
}

void exSleep(){
	char msg[30];
	do{
		AppLib_readFromHost(msg,30);
		AppLib_writeToHostF("Hai scritto <%s> \n",msg);
	} while(strncmp(msg,"end",3)!=0);
}

void exNewTerminal(){
	pid_t pid;
    if ((pid = fork()) < 0) {
    	AppLib_writeToHost("Errore nel creare la nuova sessione!\n");
    } else if (pid == 0) {      /* child */
    	execlp("./launchTerminal", (char *)0);
    	exit(0);
    }
    AppLib_writeToHost("Avviata una nuova sessione!\n");
}

/**
 * @brief Comando che termina la sessione corrente.
 */
void exEnd(){
	HostSession* session = AppLib_getMySession();
	AppLib_writeToHostF("Chiusura della sessione %d..",session->keySession);
	AppLib_closeMySession();
}

#define NUM_COMMAND_DEFINED 6

SimpleDescCommand defcmd[] = {
		{"help","Fornisce le informazioni sui comandi disponibili",exGetsAllCommands},
		{"exit","Esce dall'applicazione",exCloseProgram},
		{"sessions","Visualizza le sessioni registrate in memoria",exGetSessions},
		{"chat","Avvia l'esecuzione di una chat.",exStartChat},
		{"end","Termina la sessione corrente.",exEnd},
		//{"sleep","Avvia una thread dormiente",exSleep},
		{"newTerminal","Avvia un nuovo terminale per comunicare con il processo", exNewTerminal}
};

/**
 * @brief Funzione pubblica che permette di caricare tutti i comandi definiti per la libreria.
 */
void cutility_LoadAllCommands(){
	int i;
	for(i=0;i<NUM_COMMAND_DEFINED;i++){
		HiddenType helpfnc = { (void*) defcmd[i].helpstr, getHiddenTypeToString };
		InterfaceCommand regcmd;
		Command_initComplete(&regcmd, defcmd[i].namecmd,defcmd[i].execfnc,&helpfnc,NULL);
		envFact_registerCMD(&regcmd);
	}
}


